import { Article, IArticle } from '../models/article'
import {
  DatabaseError,
  NotFoundError,
  ValidationError
} from '../errors/CustomError'
import { isMongoError } from '../errors/MongoError'

class ArticleService {
  // 创建文章
  async create(articleData: Partial<IArticle>): Promise<IArticle> {
    try {
      const article = new Article(articleData)
      return await article.save()
    } catch (error) {
      if (isMongoError(error) && error.code === 11000) {
        const mongoError = error as any
        if (mongoError.keyValue?.title) {
          throw new ValidationError('文章标题已存在')
        }
        throw new ValidationError('文章数据重复')
      }

      if (error instanceof Error && error.name === 'ValidationError') {
        throw new ValidationError('文章数据验证失败', (error as any).errors)
      }

      throw new DatabaseError('创建文章失败', error)
    }
  }

  // 删除文章
  async delete(id: number): Promise<boolean> {
    try {
      const result = await Article.findOneAndDelete({ id })

      if (!result) {
        throw new NotFoundError('文章未找到')
      }

      return true
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('删除文章失败')
    }
  }

  // 更新文章
  async update(
    id: number,
    updateData: Partial<IArticle>
  ): Promise<IArticle | null> {
    try {
      // 移除不能更新的字段
      const { created_at, ...updateFields } = updateData

      const article = await Article.findOneAndUpdate({ id }, updateFields, {
        new: true
      })

      if (!article) {
        throw new NotFoundError('文章未找到')
      }

      return article
    } catch (error) {
      if (error instanceof NotFoundError || error instanceof ValidationError) {
        throw error
      }
      if (isMongoError(error) && error.code === 11000) {
        const mongoError = error as any
        if (mongoError.keyValue?.title) {
          throw new ValidationError('文章标题已存在')
        }
        throw new ValidationError('文章数据重复')
      }

      if (error instanceof Error && error.name === 'ValidationError') {
        throw new ValidationError('文章数据验证失败', (error as any).errors)
      }
      throw new DatabaseError('更新文章失败')
    }
  }

  // 增加浏览量
  async increaseViewCount(id: number): Promise<IArticle | null> {
    try {
      const article = await Article.findOneAndUpdate(
        { id },
        { $inc: { view_count: 1 } },
        { new: true }
      )

      if (!article) {
        throw new NotFoundError('文章未找到')
      }

      return article
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('更新文章浏览量失败')
    }
  }

  // 查询所有文章
  async findAll(query: any = {}): Promise<{ list: IArticle[]; total: number }> {
    try {
      const page = Math.max(Number(query.page) || 1, 1)
      const size = Math.max(Number(query.size) || 10, 1)
      const skip = (page - 1) * size

      const filter: any = {}

      // 根据状态过滤
      if (query.status) {
        filter.status = parseInt(query.status as string)
      }

      // 根据分类过滤
      if (query.category_id) {
        filter.category_id = { $in: [parseInt(query.category_id as string)] }
      }

      // 根据标题搜索
      if (query.title) {
        filter.title = { $regex: query.title, $options: 'i' }
      }

      // 根据查询条件计算总数
      const total = await Article.countDocuments(filter)

      const articles = await Article.find(filter).skip(skip).limit(size)
      const list = articles.map((article) => {
        return article.toJSON() as unknown as IArticle
      })
      return {
        list,
        total
      }
    } catch (error) {
      throw new DatabaseError('查询文章列表失败')
    }
  }

  // 查询单个文章
  async findOne(id: number): Promise<IArticle | null> {
    try {
      const article = await Article.findOne({ id })

      if (!article) {
        throw new NotFoundError('文章未找到')
      }

      return article
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('查询文章失败')
    }
  }
}

export default new ArticleService()
